home *** CD-ROM | disk | FTP | other *** search
-
- {
- >does anyone know the file format for a doom wad in pascal? This would
- >really be helpful for me. Thanx a lot.
- I bet you really wanted a few pages of mostly uncommented source code, right?
- And not just that, but it's pretty poorly written too :)
-
- }
- Program WADRead;
- {$M 65520, 0, 0}
-
- {Interface}
-
- Uses DOS, Crt, Strings, Mode13h; { unit MODE13H at end of snipet }
-
- Type
- String8 = String [8];
- TWAD_Type = (Internal, Patch);
- StringZ8 = Array [1..8] Of Char;
-
- TRawPalette = Array [1..768] Of Byte;
- PRawPalette = ^TRawPalette;
-
- Const
- TWAD_TypeString: Array [1..2] Of String [4] = ('IWAD', 'PWAD');
-
- Var
- WAD_File: File;
- WAD_Name: String;
- WAD_Type: TWAD_Type;
- WAD_NumEntries, WAD_DirectoryPointer: LongInt;
- RawTexture: Array [1..32767] Of Byte;
- RawPalette: Array [1..768 * 14] Of Byte;
-
- {Implementation}
-
- {Add a backslash to the end of a directory name}
- {From my TTString unit, part of my TurboTools library}
- Function TT_AddSlash (S : String) : String;
- Var
- L : Byte Absolute S;
-
- Begin
- If (L > 0) And (S [L] <> '\') Then
- Begin
- Inc (L);
- S [L] := '\';
- End;
- TT_AddSlash := S;
- End;
-
- {Fill out string with spaces}
- {From TTString}
- Function TT_PadString (S: String; L: Integer) : String;
- Var
- I: Integer;
-
- Begin
- For I := Length (S) + 1 To L Do
- S [I] := #32;
- S [0] := Chr (L);
- TT_PadString := S;
- End;
-
-
- {Open the specified WAD file}
- {If FileName = '' then try DOOM.WAD, DOOM2.WAD, then search}
- {for the first WAD in the directory}
- Function WAD_Open (FileName: String): Boolean;
- Function WAD_OpenFile: Boolean;
- Var
- FileFound: SearchRec;
-
- Begin
- If Length (FileName) = 0 Then Begin
- {User hasn't specified a file name, open in the current directory}
-
- {Try to open DOOM.WAD in the current directory}
- Assign (WAD_File, 'DOOM.WAD');
- {$I-}
- Reset (WAD_File, 1);
- {$I+}
- If IOResult = 0 Then Begin
- {Succesfully opened DOOM.WAD}
- GetDir (0, WAD_Name);
- WAD_Name := TT_AddSlash (WAD_Name) + 'DOOM.WAD';
- WAD_OpenFile := True;
- Exit;
- End;
-
- {Couldn't open DOOM.WAD, try DOOM2.WAD}
- Assign (WAD_File, 'DOOM2.WAD');
- {$I-}
- Reset (WAD_File, 1);
- {$I+}
- If IOResult = 0 Then Begin
- {Succesfully opened DOOM2.WAD}
- GetDir (0, WAD_Name);
- WAD_Name := TT_AddSlash (WAD_Name) + 'DOOM2.WAD';
- WAD_OpenFile := True;
- Exit;
- End;
-
- {Couldn't open DOOM2.WAD, try opening the first WAD we find}
- FindFirst ('*.WAD', AnyFile, FileFound);
- If DOSError = 0 Then Begin
- {Found a WAD file}
- GetDir (0, WAD_Name);
- WAD_Name := TT_AddSlash (WAD_Name) + FileFound. Name;
- Assign (WAD_File, WAD_Name);
- {$I-}
- Reset (WAD_File, 1);
- {$I+}
- WAD_OpenFile := (IOResult = 0);
- Exit;
- End;
-
- {Couldn't open or find any WADs}
- WAD_OpenFile := False;
- Exit;
- End Else Begin
- {User specified a WAD file name}
- Assign (WAD_File, FileName);
- {$I-}
- Reset (WAD_File, 1);
- {$I+}
- If IOResult = 0 Then Begin
- {Succesfully opened specified WAD file}
- WAD_Name := FExpand (FileName);
- WAD_OpenFile := True;
- Exit;
- End;
-
- {Unable to open specified WAD file}
- WAD_OpenFile := False;
- End;
- End;
-
- Var
- IDString: Array [1..4] Of Char;
-
- Begin
- If WAD_OpenFile Then Begin
- {Check the first 4 byte to determine WAD type (and if it's valid)}
- BlockRead (WAD_File, IDString, 4);
- If IDString = TWAD_TypeString [1] Then
- WAD_Type := Internal
- Else If IDString = TWAD_TypeString [2] Then
- WAD_Type := Patch
- Else Begin
- WAD_Open := False;
- Exit;
- End;
- {Read in the other header data, number of entries and the pointer to}
- {the directory at the end of the file}
- BlockRead (WAD_File, WAD_NumEntries, 4);
- BlockRead (WAD_File, WAD_DirectoryPointer, 4);
- End Else
- WAD_Open := False;
- End;
-
- {Read in directory entry EntryNum (0 based)}
- Function WAD_ReadEntry (EntryNum: LongInt; var Start, Length: LongInt; var Ent
- Var
- EntryNameZ: StringZ8;
-
- Begin
- {$I-}
- Seek (WAD_File, WAD_DirectoryPointer + (EntryNum * 16));
- {$I+}
- If IOResult = 0 Then Begin
- BlockRead (WAD_File, Start, 4);
- BlockRead (WAD_File, Length, 4);
- BlockRead (WAD_File, EntryNameZ, 8);
- EntryName := StrPas (@EntryNameZ);
- WAD_ReadEntry := True;
- End Else
- WAD_ReadEntry := False;
- End;
-
- {Search for directory entry with name EntryName (case sensitive)}
- Function WAD_FindEntry (EntryName: String8): LongInt;
- Var
- EntryNum, Start, Length: LongInt;
- CurEntryName: String8;
-
- Begin
- For EntryNum := 0 To WAD_NumEntries - 1 Do
- If Not WAD_ReadEntry (EntryNum, Start, Length, CurEntryName) Then Begin
- WAD_FindEntry := -2;
- Exit;
- End Else
- If CurEntryName = EntryName Then Begin
- WAD_FindEntry := EntryNum;
- Exit;
- End;
- WAD_FindEntry := -1;
- End;
-
- {Read in the data for a directory entry. Use WAD_ReadEntry first}
- Function WAD_ReadEntryData (Start, Length: LongInt; Data: Pointer): Boolean;
- Begin
- {$I-}
- Seek (WAD_File, Start);
- BlockRead (WAD_File, Data^, Length);
- {$I+}
- WAD_ReadEntryData := (IOResult = 0);
- End;
-
- Procedure WAD_DisplayTile (RawTexture: Array of Byte);
- Var
- Line: Byte;
-
- Begin
- For Line := 0 To 63 Do
- Move (RawTexture [Line * 64], Mem [$A000:Line * 320], 64);
- { Repeat Until KeyPressed;
- TextMode (LastMode);}
- End;
-
- Procedure WAD_SetPalette (RawPalette: PRawPalette); {[1..768]}
- Var
- Color: Byte;
-
- Begin
- For Color := 0 To 255 Do
- Mode13h. SetCol (Color, RawPalette^ [Color * 3 + 1] div 4 ,
- RawPalette^ [Color * 3 + 2] div 4,
- RawPalette^ [Color * 3 + 3] div 4);
- End;
-
- Procedure WAD_DisplaySprite (RawSprite: Array of Byte);
- Var
- Width, Height, Left, Top, X, Y, Column: Word;
- ColumnOffset, PixelOffset: LongInt;
- Pixel, Count: Byte;
-
- Begin
- Move (RawSprite [0], Width, 2);
- Move (RawSprite [2], Height, 2);
- Move (RawSprite [4], Left, 2);
- Move (RawSprite [6], Top, 2);
- For Column := 1 To Width Do Begin
- X := Column - 1;
- Move (RawSprite [4 + Column * 4], ColumnOffset, 4);
-
- Repeat
- {for each post}
- If Not (RawSprite [ColumnOffset] = $FF) Then Begin
- Y := RawSprite [ColumnOffset];
- Count := RawSprite [ColumnOffset + 1];
- For PixelOffset := ColumnOffset + 3 To ColumnOffset + Count + 2 Do Begi
- Inc (Y);
- PlotPixel (X, Y, RawSprite [PixelOffset]);
- End;
- ColumnOffset := ColumnOffset + Count + 4;
- End;
- Until RawSprite [ColumnOffset] = $FF;
- End;
- End;
-
- Var
- Entry, Start, Length: LongInt;
- Success: Boolean;
- EntryName, WhichEntry: String8;
-
- Begin
- ClrScr;
- WriteLn ('Enter path to WAD file');
- Write (': ');
- ReadLn (WAD_Name);
-
- Success := WAD_Open (WAD_Name);
- If Not Success Then Begin
- WriteLn ('Unable to open ' + WAD_Name);
- Halt;
- End;
-
- WriteLn ('Opened: ', WAD_Name);
- WriteLn ('Wad type: ', Ord (WAD_Type));
- WriteLn ('Num entries: ', WAD_NumEntries);
- WriteLn ('Pointer to Directory: ', WAD_DirectoryPointer);
-
- WriteLn;
- WriteLn ('Press any key to continue...');
- Repeat Until KeyPressed;
- ReadKey;
-
- WriteLn;
- WriteLn ('Directory Entries: ');
- For Entry := 0 To WAD_NumEntries - 1 Do Begin
- WAD_ReadEntry (Entry, Start, Length, EntryName);
- Write (TT_PadString (EntryName, 10));
- End;
-
- WriteLn ('Display which title?');
- Write (': ');
- ReadLn (WhichEntry);
- If WhichEntry = '' Then
- Halt;
-
- Mode13h.Init;
- WAD_ReadEntry (WAD_FindEntry ('PLAYPAL'), Start, Length, EntryName);
- WAD_ReadEntryData (Start, Length, @RawPalette);
- WAD_ReadEntry (WAD_FindEntry (WhichEntry), Start, Length, EntryName);
- WAD_ReadEntryData (Start, Length, @RawTexture);
- WAD_SetPalette (@RawPalette [6145]);
- { WAD_DisplayTile (RawTexture);}
- WAD_DisplaySprite (RawTexture);
- For Entry := 8 DownTo 0 Do Begin
- Mode13h. WaitRetrace;
- WAD_SetPalette (@RawPalette [768 * Entry+ 1]);
- Delay (20);
-
- End;
- Repeat Until KeyPressed;
- TextMode (LastMode);
- End.
- ***
-
- Now you need my boring Mode13h unit:
-
- *** C:\TP\WORK\MODE13H.PAS
- Unit Mode13h;
-
- Interface
-
- Procedure GetCol(C : Byte; Var R, G, B : Byte);
- Procedure SetCol(C, R, G, B : Byte);
- Procedure Init;
- Procedure PlotPixel (X, Y: Word; Color: Byte);
- Procedure WaitRetrace;
-
- Implementation
-
- Const PelAddrRgR = $3C7;
- PelAddrRgW = $3C8;
- PelDataReg = $3C9;
-
- Procedure GetCol(C : Byte; Var R, G, B : Byte);
- Begin
- Port[PelAddrRgR] := C;
- R := Port[PelDataReg];
- G := Port[PelDataReg];
- B := Port[PelDataReg];
- End;
-
- Procedure SetCol(C, R, G, B : Byte);
- Begin
- Port[PelAddrRgW] := C;
- Port[PelDataReg] := R;
- Port[PelDataReg] := G;
- Port[PelDataReg] := B;
- End;
-
- Procedure Init; Assembler;
- Asm
- mov ax, 13h
- int 10h
- End;
-
- Procedure PlotPixel (X, Y: Word; Color: Byte); Assembler;
- Asm
- push es
- push di
- mov ax, Y
- mov bx, ax
- shl ax, 8
- shl bx, 6
- add ax, bx
- add ax, X
- mov di, ax
- mov ax, 0A000h
- mov es, ax
- mov al, Color
- mov es:[di], al
- pop di
- pop es
- End;
-
- Procedure WaitRetrace; Assembler;
- Asm;
- mov dx, 03DAh
- @@WaitRetrace_LoopA:
- in al, dx
- and al, 08h
- jnz @@WaitRetrace_LoopA
- @@WaitRetrace_LoopB:
- in al, dx
- and al, 08h
- jz @@WaitRetrace_LoopB
- End;
-
- Begin
- End.